using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using BinaryComponents.SuperList;

namespace EventScavenger
{
    public delegate void UpdateAnalizerDataDelegate(ref EventEntry[] eventEntries);

    public partial class EventAnalizer : Form
    {
        public EventAnalizer()
        {
            InitializeComponent();
        }

        public event UpdateAnalizerDataDelegate UpdateAnalizerData;

        #region Privates
        private readonly int detailTextPanelMinSize = 16;
        private string ipAddressPattern = @"\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b";
        private string guidPattern = @"[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}";
        #endregion

        #region Public methods
        public void ShowAnylizer(EventEntry[] eventEntries)
        {
            this.Show();
            splitContainer1.SplitterDistance = splitContainer1.Height - detailTextPanelMinSize;
            lstEvents.CollapseAll();
            Column machineColumn = new Column("machine", "Machine", 100, delegate(object item) { return ((EventEntry)item).MachineName; });
            Column logColumn = new Column("log", "Log", 100, delegate(object item) { return ((EventEntry)item).LogName; });
            Column typeColumn = new Column("type", "Type", 100, delegate(object item) { return ((EventEntry)item).EventTypeName; }, delegate(object item) { return ((EventEntry)item).EventTypeName == "Error" ? new Font(FontFamily.GenericSansSerif, 8, FontStyle.Bold) : new Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular); });
            Column dateColumn = new Column("date", "Date", 120, delegate(object item) { return ((EventEntry)item).TimeGenerated; });
            Column sourceColumn = new Column("source", "Source", 120, delegate(object item) { return ((EventEntry)item).SourceName; });
            Column eventIDColumn = new Column("eventID", "EventID", 100, delegate(object item) { return ((EventEntry)item).EventID; });
            Column messageColumn = new Column("message", "Message", 300, delegate(object item) { string msg = ((EventEntry)item).Message.Replace("\r\n", "_"); if (msg.Length > 80) return msg.Substring(0, 80); else return msg; });
            Column dateYearColumn = new Column("year", "Year", 50, delegate(object item) { return ((EventEntry)item).TimeGenerated.Year.ToString(); });
            Column dateMonthColumn = new Column("month", "Month", 50, delegate(object item) { return ((EventEntry)item).TimeGenerated.Month.ToString().PadLeft(2, ' '); });
            Column dateDayColumn = new Column("day", "Day", 50, delegate(object item) { return ((EventEntry)item).TimeGenerated.Day.ToString().PadLeft(2, ' '); });
            Column dateHourColumn = new Column("hour", "Hour", 50, delegate(object item) { return ((EventEntry)item).TimeGenerated.Hour.ToString().PadLeft(2, ' '); });
            Column dateMinuteColumn = new Column("minute", "Minute", 50, delegate(object item) { return ((EventEntry)item).TimeGenerated.Minute.ToString().PadLeft(2, ' '); });
            Column dateWeekColumn = new Column("week", "Week", 50, delegate(object item) { return (((EventEntry)item).TimeGenerated.DayOfYear / 7).ToString().PadLeft(2, ' '); });
            Column ipAddressColumn = new Column("ipaddress", "IP address", 50, delegate(object item)
                {
                    System.Text.RegularExpressions.MatchCollection mc = System.Text.RegularExpressions.Regex.Matches(((EventEntry)item).Message, ipAddressPattern);
                    if (mc.Count > 0)
                        return mc[0].Value;
                    else
                        return "No IP";
                });
            Column guidColumn = new Column("guid", "Guid", 50, delegate(object item)
            {
                System.Text.RegularExpressions.MatchCollection mc = System.Text.RegularExpressions.Regex.Matches(((EventEntry)item).Message, guidPattern);
                if (mc.Count > 0)
                    return mc[0].Value;
                else
                    return "No Guid";
            });


            dateColumn.GroupItemAccessor = new ColumnItemValueAccessor(GroupValueFromItem);
            dateColumn.MoveBehaviour = Column.MoveToGroupBehaviour.Copy;

            dateColumn.GroupSortOrder = SortOrder.Descending;

            lstEvents.Columns.Clear();
            lstEvents.Columns.Add(dateColumn);
            lstEvents.Columns.Add(machineColumn);
            lstEvents.Columns.Add(logColumn);
            lstEvents.Columns.Add(sourceColumn);
            lstEvents.Columns.Add(eventIDColumn);
            lstEvents.Columns.Add(typeColumn);
            lstEvents.Columns.Add(messageColumn);

            lstEvents.Columns.GroupedItems.Add(dateYearColumn);
            lstEvents.Columns.GroupedItems.Add(dateMonthColumn);
            lstEvents.Columns.GroupedItems.Add(dateDayColumn);
            lstEvents.Columns.GroupedItems.Add(dateHourColumn);
            lstEvents.Columns.GroupedItems.Add(dateMinuteColumn);
            lstEvents.Columns.GroupedItems.Add(dateWeekColumn);
            lstEvents.Columns.GroupedItems.Add(ipAddressColumn);
            lstEvents.Columns.GroupedItems.Add(guidColumn);

            lstEvents.GroupSeperatorColor = Color.WhiteSmoke;
            lstEvents.RowSeperatorColor = Color.WhiteSmoke;
            LoadEntries(eventEntries);

            lstEvents.Columns.GroupedItems.Remove(dateHourColumn);
            lstEvents.Columns.GroupedItems.Remove(dateMinuteColumn);
            lstEvents.Columns.GroupedItems.Remove(dateWeekColumn);
            lstEvents.Columns.GroupedItems.Remove(ipAddressColumn);
            lstEvents.Columns.GroupedItems.Remove(guidColumn);
        } 
        #endregion

        #region Form events
        private void EventAnalizer_Load(object sender, EventArgs e)
        {
            splitContainer1.Panel2Collapsed = true;
        }
        private void EventAnalizer_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F5)
            {
                if (UpdateAnalizerData != null)
                {
                    EventEntry[] eventEntries = new EventEntry[1];
                    UpdateAnalizerData(ref eventEntries);
                    LoadEntries(eventEntries);
                }
            }
            if (e.KeyCode == Keys.F8)
            {
                cmdToggleHideDetails_Click(sender, e);
            }
        }
        #endregion

        #region ListView events
        private void lstEvents_SelectedIndexChanged(object sender, EventArgs e)
        {
            timerShowDetail.Enabled = true;
        }
        #endregion

        #region Loading data
        private void LoadEntries(EventEntry[] eventEntries)
        {


            try
            {
                lstEvents.Items.Clear();
                lstEvents.Items.AddRange(eventEntries);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        private string GroupValueFromItem(object o)
        {
            DateTime publicationDate = ((EventEntry)o).TimeGenerated;
            DateTime now = DateTime.Now;
            DateTime hourBefore = DateTime.Now.AddHours(-1);
            DateTime today = now.Date;
            DateTime weekStart = today.AddDays(1 - (int)today.DayOfWeek);
            DateTime monthStart = today.AddDays(1 - today.Day);

            double days = DateTime.Now.Subtract(publicationDate).TotalDays;

            if (publicationDate > hourBefore)
            {
                return "Last Hour";
            }
            else if (publicationDate > today)
            {
                return "Today";
            }
            else if (publicationDate > today.AddDays(-1))
            {
                return "Yesterday";
            }
            else if (publicationDate > weekStart)
            {
                return "This Week";
            }
            else if (publicationDate > weekStart.AddDays(-7))
            {
                return "Last Week";
            }
            else if (publicationDate > monthStart)
            {
                return "This Month";
            }
            else if (publicationDate > monthStart.AddMonths(-1))
            {
                return "Last Month";
            }
            else if (publicationDate > monthStart.AddMonths(-3))
            {
                return "Last 3 Months";
            }
            else
            {
                return "Older";
            }
        } 
        #endregion

        #region Show/Hide detail panel
        private void cmdHidePanel_Click(object sender, EventArgs e)
        {
            splitContainer1.SplitterDistance = splitContainer1.Height - detailTextPanelMinSize;
        }
        private void cmdShowPanel_Click(object sender, EventArgs e)
        {
            splitContainer1.SplitterDistance = splitContainer1.Height - 200;
        }
        private void cmdToggleHideDetails_Click(object sender, EventArgs e)
        {
            splitContainer1.Panel2Collapsed = !splitContainer1.Panel2Collapsed;
            cmdToggleHideDetails.Text = splitContainer1.Panel2Collapsed ? "ttt" : "uuu";
            if (splitContainer1.SplitterDistance > splitContainer1.Height - 200)
                splitContainer1.SplitterDistance = splitContainer1.Height - 200;
        }
        #endregion
        
        #region Details
        private void timerShowDetail_Tick(object sender, EventArgs e)
        {
            timerShowDetail.Enabled = false;
            rtxtEntryDetail.Text = "";
            foreach (BinaryComponents.SuperList.RowIdentifier item in lstEvents.SelectedItems)
            {
                EventEntry entry = ((EventEntry)item.Items[0]);
                AddFormatRTFText("Date time :", FontStyle.Bold);
                AddFormatRTFText(entry.TimeGenerated.ToShortDateString() + " " + entry.TimeGenerated.ToShortTimeString(), FontStyle.Regular);
                AddFormatRTFText("\r\n", FontStyle.Regular);
                AddFormatRTFText("Type :", FontStyle.Bold);
                AddFormatRTFText(entry.EventTypeName, FontStyle.Regular);
                AddFormatRTFText("\r\n", FontStyle.Regular);
                AddFormatRTFText("Machine\\Log :", FontStyle.Bold);
                AddFormatRTFText(entry.MachineName + "\\" + entry.LogName, FontStyle.Regular);
                AddFormatRTFText("\r\n", FontStyle.Regular);
                AddFormatRTFText("Source :", FontStyle.Bold);
                AddFormatRTFText(entry.SourceName, FontStyle.Regular);
                AddFormatRTFText("\r\n", FontStyle.Regular);
                AddFormatRTFText("Event ID :", FontStyle.Bold);
                AddFormatRTFText(entry.EventID.ToString(), FontStyle.Regular);
                AddFormatRTFText("\r\n", FontStyle.Regular);
                AddFormatRTFText("User :", FontStyle.Bold);
                AddFormatRTFText(entry.UserName, FontStyle.Regular);
                AddFormatRTFText("\r\n", FontStyle.Regular);
                AddFormatRTFText("Message :", FontStyle.Bold);
                AddFormatRTFText("\r\n", FontStyle.Regular);
                AddFormatRTFText(entry.Message, FontStyle.Regular);
                AddFormatRTFText("\r\n-------------------------------------------\r\n\r\n", FontStyle.Regular);
            }
            rtxtEntryDetail.SelectionStart = 0;
            rtxtEntryDetail.SelectionLength = 0;
        }
        private void AddFormatRTFText(string text, FontStyle fs)
        {
            rtxtEntryDetail.AppendText(text);
            if (text.Replace("\r", "").Replace("\n", "").Length > 0)
            {
                rtxtEntryDetail.SelectionStart = rtxtEntryDetail.Text.Length - text.Replace("\r", "").Replace("\n", "").Length;
                rtxtEntryDetail.SelectionLength = text.Replace("\r", "").Replace("\n", "").Length;
                rtxtEntryDetail.SelectionFont = new Font("Microsoft Sans Serif", 8, fs);
            }
        }
        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            rtxtEntryDetail.Copy();
        } 
        #endregion


    }
}